﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace PlanningPoker
{
	public class Game
	{
		private static Game staticGame = new Game();
		private Game()
		{
		}

		public static bool Join(System.Web.UI.Page page, string name)
		{
			SetName(page, name);
			return staticGame.Join(name);
		}

		private static void SetName(System.Web.UI.Page page, string name)
		{
			page.Session["name"] = name;
		}

		private static string GetName(System.Web.UI.Page page)
		{
			return (string)page.Session["name"];
		}

		private List<string> players = new List<string>();
		public static List<string> Players
		{
			get
			{
				return staticGame._Players;
			}
		}

		public static bool PlayCard(System.Web.UI.Page page, string card)
		{
			return staticGame.PlayCard(GetName(page), card);
		}

		public static bool IsJoined(System.Web.UI.Page page)
		{
			return staticGame.IsJoined(GetName(page));
		}

		public static Result Result
		{
			get
			{
				return staticGame._Result;
			}
		}

		public static bool BackCard(System.Web.UI.Page page)
		{
			return staticGame.BackCard(GetName(page));
		}

		public static void Leave(System.Web.UI.Page page)
		{
			staticGame.Leave(GetName(page));
		}

		private List<string> _Players
		{
			get
			{
				lock (this)
				{
					return players.ToList<string>();
				}
			}
		}

		private bool Join(string name)
		{
			if (string.IsNullOrEmpty(name))
				return false;
			lock (this)
			{
				if (players.Contains(name))
					return true;
				players.Add(name);
				return true;
			}
		}

		private List<CardInfo> cards = new List<CardInfo>();
		private bool PlayCard(string name, string card)
		{
			if (string.IsNullOrEmpty(name))
				return false;
			if (string.IsNullOrEmpty(card))
				return false;
			lock (this)
			{
				if (false == players.Contains(name))
					return false;
				if (0 < cards.Count(c => c.Player.Equals(name)))
					return false;
				cards.Add(new CardInfo(name, card));
			}
			return true;
		}

		private bool IsJoined(string name)
		{
			lock (this)
			{
				return players.Contains(name);
			}
		}

		public Result _Result
		{
			get
			{
				if(AllPlayed())
					return new ResultOpened(cards);
				else
					return new ResultClosed(cards);
			}
		}

		private bool AllPlayed()
		{
			lock (this)
			{
				return players.Count == cards.Count;
			}
		}

		private bool BackCard(string name)
		{
			if (string.IsNullOrEmpty(name))
				return false;

			lock (this)
			{
				if (false == players.Contains(name))
					return false;
				return 1 <= cards.RemoveAll(c => c.Player.Equals(name));
			}
		}

		private void Leave(string name)
		{
			if (string.IsNullOrEmpty(name))
				return;

			lock (this)
			{
				players.Remove(name);
				cards.RemoveAll(c => c.Player.Equals(name));
			}
		}
	}
}